package org.Yiran.timetale_re.datagen;

import net.minecraft.core.HolderLookup;
import net.minecraft.data.PackOutput;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraftforge.common.data.BlockTagsProvider;
import net.minecraftforge.common.data.ExistingFileHelper;
import org.Yiran.timetale_re.Timetale_re;
import org.Yiran.timetale_re.block.BlocksRegister;
import org.Yiran.timetale_re.item.MaterialRegister;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.concurrent.CompletableFuture;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 方块标签生成器
 * 负责为模组中的方块生成数据包标签，包括挖掘工具类型和工具等级要求
 * 这些标签用于控制方块的挖掘行为和工具需求
 */
public class BlockTagsGenerator extends BlockTagsProvider {
    private static final Logger LOGGER = LoggerFactory.getLogger(BlockTagsGenerator.class);
    
    // ==================== 构造函数 ====================
    
    /**
     * 构造函数
     * @param output 数据包输出
     * @param lookupProvider 注册表查找提供器
     * @param existingFileHelper 现有文件助手
     */
    public BlockTagsGenerator(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider, 
                             @Nullable ExistingFileHelper existingFileHelper) {
        super(output, lookupProvider, Timetale_re.MODID, existingFileHelper);
        LOGGER.info("创建方块标签生成器");
    }

    // ==================== 标签添加方法 ====================
    
    /**
     * 添加方块标签
     * 为模组中的方块添加各种标签，包括挖掘工具类型和工具等级要求
     * 
     * @param provider 注册表查找提供器
     */
    @Override
    protected void addTags(HolderLookup.@NotNull Provider provider) {
        LOGGER.info("开始生成方块标签...");
        
        // 为所有矿石添加镐挖掘标签
        var pickaxeMineable = this.tag(BlockTags.MINEABLE_WITH_PICKAXE);
        LOGGER.debug("创建镐可挖掘标签");

        // 为斧子添加可挖掘标签
        var axeMineable = this.tag(BlockTags.MINEABLE_WITH_AXE);
        LOGGER.debug("创建斧子可挖掘标签");

        // 为铲子添加可挖掘标签
        var shovelMineable = this.tag(BlockTags.MINEABLE_WITH_SHOVEL);
        LOGGER.debug("创建铲子可挖掘标签");

        // 为凿子添加可挖掘标签
        var chiselMineable = this.tag(BlockTags.create(ResourceLocation.fromNamespaceAndPath(Timetale_re.MODID, "mineable/chisel")));
        LOGGER.debug("创建凿子可挖掘标签");

        // 处理模组方块的挖掘工具标签
        LOGGER.info("开始处理模组方块的挖掘工具标签");
        processModBlocksMineableTags(pickaxeMineable, axeMineable, shovelMineable, chiselMineable);
        
        // 遍历所有注册的材料，为有矿石的材料添加标签
        LOGGER.info("开始处理 {} 种材料的标签", MaterialRegister.getRegisteredMaterials().size());
        int processedMaterials = 0;
        
        for (MaterialRegister.MaterialDefinition material : MaterialRegister.getRegisteredMaterials()) {
            LOGGER.debug("处理材料: {}", material.getName());
            int materialTagsAdded = 0;
            
            if (material.hasOre()) {
                // 添加普通矿石
                if (material.getOre() != null) {
                    pickaxeMineable.add(material.getOre().get());
                    materialTagsAdded++;
                    LOGGER.debug("  添加普通矿石: {}", material.getOre().get());
                }

                // 添加深板岩矿石
                if (material.getDeepslateOre() != null) {
                    pickaxeMineable.add(material.getDeepslateOre().get());
                    materialTagsAdded++;
                    LOGGER.debug("  添加深板岩矿石: {}", material.getDeepslateOre().get());
                }
            }

            // 添加粗矿块的镐挖掘标签
            if (material.hasRawBlock() && material.getRawBlock() != null) {
                pickaxeMineable.add(material.getRawBlock().get());
                materialTagsAdded++;
                LOGGER.debug("  添加粗矿块: {}", material.getRawBlock().get());
            }

            // 添加金属块的镐挖掘标签
            if (material.hasType(MaterialRegister.MaterialType.BLOCK) && material.getBlock() != null) {
                pickaxeMineable.add(material.getBlock().get());
                materialTagsAdded++;
                LOGGER.debug("  添加金属块: {}", material.getBlock().get());
            }
            
            if (materialTagsAdded > 0) {
                processedMaterials++;
            }
        }
        
        LOGGER.info("完成处理 {} 种材料的挖掘工具标签", processedMaterials);

        // 为凿子添加可挖掘的石头类方块
        LOGGER.debug("添加凿子可挖掘的原版方块");
        chiselMineable.add(Blocks.STONE);
        chiselMineable.add(Blocks.COBBLESTONE);
        chiselMineable.add(Blocks.MOSSY_COBBLESTONE);
        chiselMineable.add(Blocks.COBBLED_DEEPSLATE);

        // 根据挖掘等级添加需要的工具等级标签
        LOGGER.info("开始生成工具等级标签");
        addToolLevelTags();
        
        // 处理模组方块的挖掘等级标签
        LOGGER.info("开始处理模组方块的挖掘等级标签");
        processModBlocksHarvestLevelTags();
        
        LOGGER.info("方块标签生成完成！");
    }

    // ==================== 模组方块挖掘标签处理 ====================
    
    /**
     * 处理模组方块的挖掘工具标签
     * 根据方块的MineableType分类自动添加到相应的挖掘标签中
     */
    private void processModBlocksMineableTags(IntrinsicTagAppender<Block> pickaxeTag, IntrinsicTagAppender<Block> axeTag, IntrinsicTagAppender<Block> shovelTag, IntrinsicTagAppender<Block> chiselTag) {
        int pickaxeCount = 0, axeCount = 0, shovelCount = 0, chiselCount = 0, noneCount = 0;
        
        // 处理镐可挖掘方块
        for (BlocksRegister.ModBlocks block : BlocksRegister.ModBlocks.getBlocksByMineableType(BlocksRegister.MineableType.PICKAXE)) {
            pickaxeTag.add(block.getBlock().get());
            pickaxeCount++;
            LOGGER.debug("添加镐可挖掘方块: {}", block.getBlock().get());
        }
        
        // 处理斧可挖掘方块
        for (BlocksRegister.ModBlocks block : BlocksRegister.ModBlocks.getBlocksByMineableType(BlocksRegister.MineableType.AXE)) {
            axeTag.add(block.getBlock().get());
            axeCount++;
            LOGGER.debug("添加斧可挖掘方块: {}", block.getBlock().get());
        }
        
        // 处理铲可挖掘方块
        for (BlocksRegister.ModBlocks block : BlocksRegister.ModBlocks.getBlocksByMineableType(BlocksRegister.MineableType.SHOVEL)) {
            shovelTag.add(block.getBlock().get());
            shovelCount++;
            LOGGER.debug("添加铲可挖掘方块: {}", block.getBlock().get());
        }
        
        // 处理凿子可挖掘方块
        for (BlocksRegister.ModBlocks block : BlocksRegister.ModBlocks.getBlocksByMineableType(BlocksRegister.MineableType.CHISEL)) {
            chiselTag.add(block.getBlock().get());
            chiselCount++;
            LOGGER.debug("添加凿子可挖掘方块: {}", block.getBlock().get());
        }
        
        // 记录无需工具的方块
        for (BlocksRegister.ModBlocks block : BlocksRegister.ModBlocks.getBlocksByMineableType(BlocksRegister.MineableType.NONE)) {
            noneCount++;
            LOGGER.debug("记录无需工具方块: {}", block.getBlock().get());
        }
        
        LOGGER.info("模组方块挖掘工具标签处理完成！镐: {} 个, 斧: {} 个, 铲: {} 个, 凿子: {} 个, 无需工具: {} 个", 
                   pickaxeCount, axeCount, shovelCount, chiselCount, noneCount);
    }

    /**
     * 处理模组方块的挖掘等级标签
     * 根据方块的挖掘等级添加对应的工具等级要求标签
     */
    private void processModBlocksHarvestLevelTags() {
        var needsStoneTool = this.tag(BlockTags.NEEDS_STONE_TOOL);
        var needsIronTool = this.tag(BlockTags.NEEDS_IRON_TOOL);
        var needsDiamondTool = this.tag(BlockTags.NEEDS_DIAMOND_TOOL);
        
        int stoneToolCount = 0;
        int ironToolCount = 0;
        int diamondToolCount = 0;
        
        // 处理所有模组方块
        for (BlocksRegister.ModBlocks block : BlocksRegister.ModBlocks.values()) {
            if (block.getMineableType() == BlocksRegister.MineableType.NONE) {
                continue; // 无需工具的方块跳过
            }
            
            switch (block.getHarvestLevel()) {
                case 1: // 石头工具等级
                    needsStoneTool.add(block.getBlock().get());
                    stoneToolCount++;
                    LOGGER.debug("添加需要石头工具的方块: {}", block.getBlock().get());
                    break;
                case 2: // 铁工具等级
                    needsIronTool.add(block.getBlock().get());
                    ironToolCount++;
                    LOGGER.debug("添加需要铁工具的方块: {}", block.getBlock().get());
                    break;
                case 3: // 钻石工具等级
                    needsDiamondTool.add(block.getBlock().get());
                    diamondToolCount++;
                    LOGGER.debug("添加需要钻石工具的方块: {}", block.getBlock().get());
                    break;
                default:
                    // 0级或更低等级不需要特殊工具
                    LOGGER.debug("方块 {} 不需要特殊工具", block.getBlock().get());
                    break;
            }
        }
        
        LOGGER.info("模组方块挖掘等级标签处理完成！石头工具: {} 个, 铁工具: {} 个, 钻石工具: {} 个", 
                   stoneToolCount, ironToolCount, diamondToolCount);
    }

    // ==================== 工具等级标签方法 ====================
    
    /**
     * 添加工具等级标签
     * 为不同挖掘等级的方块添加对应的工具等级要求标签
     * 控制挖掘方块所需的最低工具等级
     */
    private void addToolLevelTags() {
        LOGGER.info("开始处理工具等级标签");
        
        // 为不同挖掘等级的方块添加对应的工具等级标签
        var needsStoneTool = this.tag(BlockTags.NEEDS_STONE_TOOL);
        var needsIronTool = this.tag(BlockTags.NEEDS_IRON_TOOL);
        var needsDiamondTool = this.tag(BlockTags.NEEDS_DIAMOND_TOOL);
        
        LOGGER.debug("创建工具等级标签: 石头工具、铁工具、钻石工具");

        int stoneToolCount = 0;
        int ironToolCount = 0;
        int diamondToolCount = 0;
        
        for (MaterialRegister.MaterialDefinition material : MaterialRegister.getRegisteredMaterials()) {
            LOGGER.debug("处理材料 {} 的工具等级标签", material.getName());
            
            // 矿石的工具等级标签（原有代码保持不变）
            if (material.hasOre()) {
                // 根据挖掘等级添加对应的工具需求标签
                switch (material.getHarvestLevel()) {
                    case 1: // 石头工具等级
                        if (material.getOre() != null) {
                            needsStoneTool.add(material.getOre().get());
                            stoneToolCount++;
                            LOGGER.debug("  矿石需要石头工具: {}", material.getOre().get());
                        }
                        if (material.getDeepslateOre() != null) {
                            needsStoneTool.add(material.getDeepslateOre().get());
                            stoneToolCount++;
                            LOGGER.debug("  深板岩矿石需要石头工具: {}", material.getDeepslateOre().get());
                        }
                        break;
                    case 2: // 铁工具等级
                        if (material.getOre() != null) {
                            needsIronTool.add(material.getOre().get());
                            ironToolCount++;
                            LOGGER.debug("  矿石需要铁工具: {}", material.getOre().get());
                        }
                        if (material.getDeepslateOre() != null) {
                            needsIronTool.add(material.getDeepslateOre().get());
                            ironToolCount++;
                            LOGGER.debug("  深板岩矿石需要铁工具: {}", material.getDeepslateOre().get());
                        }
                        break;
                    case 3: // 钻石工具等级
                        if (material.getOre() != null) {
                            needsDiamondTool.add(material.getOre().get());
                            diamondToolCount++;
                            LOGGER.debug("  矿石需要钻石工具: {}", material.getOre().get());
                        }
                        if (material.getDeepslateOre() != null) {
                            needsDiamondTool.add(material.getDeepslateOre().get());
                            diamondToolCount++;
                            LOGGER.debug("  深板岩矿石需要钻石工具: {}", material.getDeepslateOre().get());
                        }
                        break;
                    default:
                        // 没有特殊工具需求的方块不需要添加标签
                        LOGGER.debug("  材料 {} 的矿石不需要特殊工具", material.getName());
                        break;
                }
            }

            // 粗矿块的工具等级标签
            if (material.hasRawBlock() && material.getRawBlock() != null) {
                switch (material.getHarvestLevel()) {
                    case 1: // 石头工具等级
                        needsStoneTool.add(material.getRawBlock().get());
                        stoneToolCount++;
                        LOGGER.debug("  粗矿块需要石头工具: {}", material.getRawBlock().get());
                        break;
                    case 2: // 铁工具等级
                        needsIronTool.add(material.getRawBlock().get());
                        ironToolCount++;
                        LOGGER.debug("  粗矿块需要铁工具: {}", material.getRawBlock().get());
                        break;
                    case 3: // 钻石工具等级
                        needsDiamondTool.add(material.getRawBlock().get());
                        diamondToolCount++;
                        LOGGER.debug("  粗矿块需要钻石工具: {}", material.getRawBlock().get());
                        break;
                    default:
                        LOGGER.debug("  材料 {} 的粗矿块不需要特殊工具", material.getName());
                        break;
                }
            }

            // 金属块的工具等级标签
            if (material.hasType(MaterialRegister.MaterialType.BLOCK) && material.getBlock() != null) {
                switch (material.getHarvestLevel()) {
                    case 1: // 石头工具等级
                        needsStoneTool.add(material.getBlock().get());
                        stoneToolCount++;
                        LOGGER.debug("  金属块需要石头工具: {}", material.getBlock().get());
                        break;
                    case 2: // 铁工具等级
                        needsIronTool.add(material.getBlock().get());
                        ironToolCount++;
                        LOGGER.debug("  金属块需要铁工具: {}", material.getBlock().get());
                        break;
                    case 3: // 钻石工具等级
                        needsDiamondTool.add(material.getBlock().get());
                        diamondToolCount++;
                        LOGGER.debug("  金属块需要钻石工具: {}", material.getBlock().get());
                        break;
                    default:
                        LOGGER.debug("  材料 {} 的金属块不需要特殊工具", material.getName());
                        break;
                }
            }
        }
        
        LOGGER.info("工具等级标签处理完成！石头工具: {} 个, 铁工具: {} 个, 钻石工具: {} 个", 
                   stoneToolCount, ironToolCount, diamondToolCount);
    }
}